package lig.com.bo;

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import lig.com.conn.ConnectionPool;
import lig.com.conn.JdbcUtil;
import lig.com.conn.LogWriter;
import lig.com.dao.AgentInfoDAO;
import lig.com.dao.ClaimDAO;
import lig.com.dao.IbnrErnDAO;
import lig.com.dao.PrmDAO;
import lig.com.dto.AgentInfoDTOList;
import lig.com.dto.AgentSummaryDTO;
import lig.com.dto.AgentSummaryDTOList;
import lig.com.dto.ClaimDTOList;
import lig.com.dto.IbnrErnDTOList;
import lig.com.dto.PrmDTO;
import lig.com.dto.PrmDTOList;
import lig.com.util.dto.StringDTO;
import lig.com.util.dto.StringPDTO;
import lig.com.util.uo.BizDateUO;

import java.math.BigDecimal;
import java.math.MathContext;


/**
 * *******************************
 * lig.com.bo
 * AgentSummaryBO.java
 * @Description :
 * *******************************
 * @author : Euijoo Lee
 * Feb 8, 2013 3:20:55 PM
 */
public class AgentSummaryBO {


	/**
	 * ************************************
	 * 1. Summary :
	 * ************************************
	 * @Method Name : main
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
			
		BizDateUO bizDateUO = new BizDateUO();
		
		Connection conn = null;
		
		try {
			
			//set connection from ConnectionPool class.
			conn = ConnectionPool.getConnection();
			int year1 = 2010; // the numbers from year1 are needed to calculate growth ratio for year2
			int year2 = 2011;
			int year3 = 2012;
			int begActdte = 201101;
			int endActdte = 201212;
			
			BigDecimal wrtValue = new BigDecimal(0);
			BigDecimal zeroValue =new BigDecimal(0);
			
			//write result to the file.
			PrintStream out = new PrintStream(new FileOutputStream("D:/OutFile5.txt"));	
			
			
			System.out.println("agentInfoDao.agentInfo Start!!!");
			
			/**
			 * ************************************
			 * Call agentInfoDao.agentInfo : Get agent information 
			 * ************************************
			 */				
			AgentInfoDAO agentInfoDao = AgentInfoDAO.getInstnace();
			AgentInfoDTOList agentInfoDTOList = new AgentInfoDTOList();			
			//agentInfoDTOList = agentInfoDao.agentInfo(conn,year1,year2);
			agentInfoDTOList = agentInfoDao.agentInfo(conn);
			
			System.out.println("Got Agent Informaiton Successfully!!!");
			System.out.println("Process start!!!");
			
			
			System.out.println("Beginning Process Time: "+ bizDateUO.nowDate() );	
			
			
			IbnrErnDAO ibnrErnDao = IbnrErnDAO.getInstnace();
			IbnrErnDTOList ibnrErnDtoList = new IbnrErnDTOList();
			ibnrErnDtoList = ibnrErnDao.IbnrErnMonthYTD(conn, year2, year3);
			int ibnrErnDtoListCnt = ibnrErnDtoList.getDtoList().size();

				// get agent information list size
				int dtoCnt = agentInfoDTOList.getDtoList().size();
				
				// Loop each agent ID 
				for(int idx = 0;idx<dtoCnt;idx++)
				{
					
					float ratio = Float.valueOf(idx)/Float.valueOf(dtoCnt)*100;
					System.out.println("In Process Row: "+idx +" Total Row: "+dtoCnt +" ratio: "+ratio +"%");
					
					/**
					 * ************************************
					 * Call prmDao.prmMonthYTD : get premiums information by agent
					 * ************************************
					 */	
					
					PrmDAO prmDao = PrmDAO.getInstnace();
					PrmDTOList prmDtoList = new PrmDTOList();
					
					prmDtoList = prmDao.prmMonthYTD(conn, year1, year2, year3,agentInfoDTOList.getDtoList().get(idx).getAgent());
					//System.out.println("Call prmDao.prmMonthYTD End: "+ bizDateUO.nowDate() );
					
					
					//Set Written premiums to calculate growth ratio
					HashMap prmYTDMap = new  HashMap();			
					int prmDtoListCnt = prmDtoList.getDtoList().size();  
					for(int prmIdx = 0;prmIdx<prmDtoListCnt;prmIdx++)
					{
						 String mapKey = Integer.toString(prmDtoList.getDtoList().get(prmIdx).getActDate());
						 BigDecimal mapValue = prmDtoList.getDtoList().get(prmIdx).getWrt();
						 prmYTDMap.put(mapKey, mapValue);						 
					}
				        
					ClaimDAO claimDao = ClaimDAO.getInstnace();
					ClaimDTOList claimDtoList = new ClaimDTOList();

					//System.out.println("Call prmDao.claimMonthYTD Start: "+ bizDateUO.nowDate() );
					claimDtoList = claimDao.claimMonthYTD(conn, year2, year3,agentInfoDTOList.getDtoList().get(idx).getAgent());
					//System.out.println("Call prmDao.prmMonthYTD End: "+ bizDateUO.nowDate() );
					int claimDtoListCnt = claimDtoList.getDtoList().size();
						
						
						//Loop data by accounting date
						for(int a=begActdte; a<endActdte+1; a++){
							
							// Set agent information into agentSummaryDto for each accounting date by each agent
							AgentSummaryDTO agentSummaryDto = new AgentSummaryDTO();
							AgentSummaryDTOList agentSummaryDTOList = new AgentSummaryDTOList();
							
							agentSummaryDto.setState(agentInfoDTOList.getDtoList().get(idx).getState());
							agentSummaryDto.setAgent(agentInfoDTOList.getDtoList().get(idx).getAgent());
							agentSummaryDto.setAgentName(agentInfoDTOList.getDtoList().get(idx).getAgentName());
							agentSummaryDto.setMarketing(agentInfoDTOList.getDtoList().get(idx).getMarketing());
							agentSummaryDto.setUnderwriter(agentInfoDTOList.getDtoList().get(idx).getUnderwriter());
							agentSummaryDto.setEthnicity(agentInfoDTOList.getDtoList().get(idx).getEthnicity());
							agentSummaryDto.setType(agentInfoDTOList.getDtoList().get(idx).getType());
							agentSummaryDto.setStatus(agentInfoDTOList.getDtoList().get(idx).getStatus());
														
							agentSummaryDto.setActdte(a);
							
							// set total earned premium for each accounting date and total IBNR Loss and IBNR Expense for each accounting date
							// These will be used to calculate incurred IBNR losses and expenses
							for (int ibErIdx = 0; ibErIdx<ibnrErnDtoListCnt; ibErIdx++){
																			
								if (a==ibnrErnDtoList.getDtoList().get(ibErIdx).getActdte()){									
									agentSummaryDto.setTotalErn(ibnrErnDtoList.getDtoList().get(ibErIdx).getTotalErn());
									
									agentSummaryDto.setIbnrLoss1(ibnrErnDtoList.getDtoList().get(ibErIdx).getIbnrLoss());
									agentSummaryDto.setIbnrExp1(ibnrErnDtoList.getDtoList().get(ibErIdx).getIbnrExp());
								}
							}
							
							// set incurred losses and expenses
							// these incurred data are before adding IBNR
							for (int claimIdx=0; claimIdx<claimDtoListCnt; claimIdx++){

								if (a==claimDtoList.getDtoList().get(claimIdx).getActdte()){
									 agentSummaryDto.setLoss1(claimDtoList.getDtoList().get(claimIdx).getLoss());
									 agentSummaryDto.setExp1(claimDtoList.getDtoList().get(claimIdx).getExp());
								 }
							}
							
							
							for(int prmIdx = 0;prmIdx<prmDtoListCnt;prmIdx++)
							 {
								
								if (a==prmDtoList.getDtoList().get(prmIdx).getActDate()){
									// set Written Premium and Earned Premium
									 agentSummaryDto.setPrem1(prmDtoList.getDtoList().get(prmIdx).getWrt());
									 agentSummaryDto.setEarn1(prmDtoList.getDtoList().get(prmIdx).getErn());
									 
									 // set earned premium ratio : earned premium / total earned premium
									 agentSummaryDto.setEarnRatio1(agentSummaryDto.getEarn1().divide(agentSummaryDto.getTotalErn(), 11, BigDecimal.ROUND_HALF_UP ));
									 
									 // Incurred Loss IBNR :  incurred Loss IBNR = ERN ration * total IBNR loss + incurred loss 
									 agentSummaryDto.setIncLossIbnr(agentSummaryDto.getEarnRatio1().multiply(agentSummaryDto.getIbnrLoss1()).add(agentSummaryDto.getLoss1()).setScale(2, BigDecimal.ROUND_HALF_UP));
									// Incurred Expense IBNR :  incurred Expense IBNR = ERN ration * total IBNR expense + incurred expense
									 agentSummaryDto.setIncExpIbnr(agentSummaryDto.getEarnRatio1().multiply(agentSummaryDto.getIbnrExp1()).add(agentSummaryDto.getExp1()).setScale(2, BigDecimal.ROUND_HALF_UP));
									 
									 // If earned premium is 0.00 then get earned premium integer 0 and set total loss ratio is 0
									 // Reason : to avoid dividing error by 0
									 if (agentSummaryDto.getEarn1().compareTo(BigDecimal.ZERO)==0){
										 agentSummaryDto.setTotalLossRatio(zeroValue);
									 }
									 // else then set total loss ratio 
									 // Total loss ratio = (incurred loss IBNR + incurred expense IBNR) / earned premium
									 else{
										 agentSummaryDto.setTotalLossRatio(((agentSummaryDto.getIncLossIbnr().add(agentSummaryDto.getIncExpIbnr())).divide(agentSummaryDto.getEarn1(), 11, BigDecimal.ROUND_HALF_UP)).setScale(2, BigDecimal.ROUND_HALF_UP)); 
									 }
									 
									 // find a year ago written premium value  
									 wrtValue = (BigDecimal) prmYTDMap.get(Integer.toString(a-100));
									 // if written premium is null then change to 0
									 if(wrtValue==null)wrtValue = BigDecimal.ZERO;
									 // if written premium is 0 then set growth ratio is 0
									 if(wrtValue.compareTo(BigDecimal.ZERO)==0){
										 agentSummaryDto.setGrowthRatio(zeroValue);
									 }
									 // else then set growth ratio
									 // growth ratio = (current WRT - a year ago WRT) / a year ago WRT
									 else{
										 agentSummaryDto.setGrowthRatio(agentSummaryDto.getPrem1().subtract(wrtValue).divide(wrtValue,2,BigDecimal.ROUND_HALF_UP));
									 } 
								 }
							 }
								// Print out all fields value to the out file
								out.println(agentSummaryDto.getState()
										+"|"+agentSummaryDto.getAgent()
										+"|"+agentSummaryDto.getAgentName()
										+"|"+agentSummaryDto.getMarketing()
										+"|"+agentSummaryDto.getUnderwriter()
										+"|"+agentSummaryDto.getEthnicity()
										+"|"+agentSummaryDto.getType()
										+"|"+agentSummaryDto.getStatus()
										+"|"+agentSummaryDto.getActdte()
								 		+"|"+agentSummaryDto.getPrem1()
										+"|"+agentSummaryDto.getEarn1()
										+"|"+agentSummaryDto.getTotalErn()
										+"|"+agentSummaryDto.getLoss1()
										+"|"+agentSummaryDto.getExp1()
										+"|"+agentSummaryDto.getIbnrLoss1()
										+"|"+agentSummaryDto.getIbnrExp1()
										+"|"+agentSummaryDto.getIncLossIbnr()
										+"|"+agentSummaryDto.getIncExpIbnr()
										+"|"+agentSummaryDto.getTotalLossRatio()
										+"|"+agentSummaryDto.getGrowthRatio()
										);	
							
							// when this turn is December then make the account date to be beginning of next year
							if (Integer.toString(a).substring(4, 6).equals("12")){
								a=a+88;
							}
						}// close for(int a=begActdte; a<endActdte+1; a++)					
				}// close for loop by idx
	
		} catch (SQLException e) {
			LogWriter.out("SQLException : " +e.getMessage());
			throw new SQLException(e);
		} catch (Exception e) {	
			LogWriter.out("Exception : " +e.getMessage());	
			throw new SQLException(e);
		} finally {
			JdbcUtil.close(conn);			
		}
		
		System.out.println("Process is completed!!!");
		System.out.println("Ending Process Time: "+ bizDateUO.nowDate() );
	}//close main

}//close class
